#include <iostream>
#include "net/proactor_engine.hpp"

using namespace shine;
using namespace shine::net;

int main(){
    std::cout << "connect address: ";
    shine::string addr;
//     std::cin >> addr;
	addr = "192.168.3.7:30003";
	addr = "127.0.0.1:30002";
	addr = "39.103.227.74:2074";
	shine::string bind_addr = "192.168.3.7:12345";
	bind_addr = "0.0.0.0:0";
	proactor_engine engine;

    auto rc = engine.add_connector("client", addr, [](bool ok, connector *conn)->bool{
        std::cout << "connect:" << ok << endl;
        if (ok)
        {
            conn->set_recv_timeout(10000);

            conn->register_recv_callback([](const int8 *data, shine::size_t len, connection *conn)->bool{
                std::cout << "recv_callback len:" << len << " data:" << data << std::endl;
//                 conn->get_timer_manager()->set_timer(5000, [conn]()->bool{
//                     shine::string str = "hello world!";
//                     conn->async_send(str.data(), str.size());                 
//                     return false;
//                 });
                return true;
            });

            conn->register_send_callback([](shine::size_t len, connection *conn)->bool{
				std::cout << HasOverlappedIoCompleted(&conn->get_send_context()) << std::endl;

                return true;
            });

            conn->register_recv_timeout_callback([](connection *conn)->bool{
                std::cout << "recv_timeout_callback:" << endl;
                return true;
            });

            conn->register_send_timeout_callback([](connection *conn)->bool{
                std::cout << "send_timeout_callback:" << endl;
                return false;
            });

            conn->register_close_callback([](connection *conn){
                std::cout << "close_callback:" << endl;
            });

            shine::string data = "ECHOhello world";
			std::cout << HasOverlappedIoCompleted(&conn->get_recv_context()) << std::endl;
			std::cout << HasOverlappedIoCompleted(&conn->get_send_context()) << std::endl;

            conn->async_send(data.data(), data.size());
			std::cout << HasOverlappedIoCompleted(&conn->get_send_context()) << std::endl;

            conn->async_recv();
			new std::thread([conn] {
				std::this_thread::sleep_for(std::chrono::seconds(2));
				std::function<void()> func = [conn] {
					BOOL rc = CancelIoEx((HANDLE)conn->get_socket_fd(), NULL);
// 					shine::net::socket::close(conn->get_socket_fd());
// 					shine::net::socket::shutdown(conn->get_socket_fd(), SD_BOTH);

					std::cout << HasOverlappedIoCompleted(&conn->get_recv_context()) << std::endl;
					std::cout << HasOverlappedIoCompleted(&conn->get_send_context()) << std::endl;
				};
// 				conn->get_engine()->queue_execute(func);
				func();
			});
        }
		return true;
    }, bind_addr, false);

// 	CancelIoEx((HANDLE)rc->get_socket_fd(), NULL);
    if (rc)
    {
        std::cout << "connect " << addr << "success." << endl;
        engine.run();
    }
    else
    {
        std::cout << "connect " << addr << "failed." << endl;
    }

    return 0;
}